/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HMSERIALIZATION_MASTER_JSON_NODE_H
#define HMSERIALIZATION_MASTER_JSON_NODE_H

#include "napi/native_api.h"
#include "yyjson.h"

typedef enum JsonDataType {
    JSON_DATA_TYPE_STRING,
    JSON_DATA_TYPE_NUMBER,
    JSON_DATA_TYPE_BIGINT,
    JSON_DATA_TYPE_BOOLEAN,

    JSON_DATA_TYPE_POINTER_OBJECT,
    JSON_DATA_TYPE_BASIC_OBJECT,
    JSON_DATA_TYPE_ARR_OBJECT
} JsonDataType;

typedef enum JsonNodeType {
    JSON_NODE_TYPE_STRING,
    JSON_NODE_TYPE_INT, // retain
    JSON_NODE_TYPE_UBIGINT,
    JSON_NODE_TYPE_BIGINT,
    JSON_NODE_TYPE_DOUBLE,
    JSON_NODE_TYPE_BOOLEAN,
    JSON_NODE_TYPE_ARRAY,
    JSON_NODE_TYPE_OBJECT,
    JSON_NODE_TYPE_NULL,

    JSON_NODE_TYPE_INVALID = 255
} JsonNodeType;

class JsonNode {
public:
    static void Destructor(napi_env env, void *nativeObject, void *finalize_hint);
    static napi_value Init(napi_env env, napi_value exports);

private:
    explicit JsonNode();
    ~JsonNode();

    static napi_value GetData(napi_env env, napi_callback_info info, JsonDataType dataType);
    static napi_value GetDataObject(napi_env env, napi_callback_info info, JsonDataType dataType);

    static void InitObjJsonValue(napi_env env, napi_value *args, JsonNode *obj);
    static napi_value New(napi_env env, napi_callback_info info);

    static napi_value DecodeFromArrayBuffer(napi_env env, napi_callback_info info);
    static napi_value DecodeFromArrayBufferAsync(napi_env env, napi_callback_info info);
    static napi_value At(napi_env env, napi_callback_info info);
    static napi_value Keys(napi_env env, napi_callback_info info);
    static napi_value GetObject(napi_env env, napi_callback_info info);
    static napi_value GetArray(napi_env env, napi_callback_info info);
    static napi_value GetArrayValue(napi_env env, napi_callback_info info);
    static napi_value GetArrayValues(napi_env env, napi_callback_info info);
    static napi_value GetString(napi_env env, napi_callback_info info);
    static napi_value GetNumber(napi_env env, napi_callback_info info);
    static napi_value GetBigInt(napi_env env, napi_callback_info info);
    static napi_value GetBoolean(napi_env env, napi_callback_info info);

    static napi_value ElementCount(napi_env env, napi_callback_info info);
    static napi_value GetType(napi_env env, napi_callback_info info);
    static napi_value GetValueTypeByKey(napi_env env, napi_callback_info info);
    static JsonNodeType GetValType(yyjson_val *val);
    static napi_value GetValueTypeByIndex(napi_env env, napi_callback_info info);
    static napi_value HasKey(napi_env env, napi_callback_info info);
    static napi_value ToString(napi_env env, napi_callback_info info);
    static napi_value ToBuffer(napi_env env, napi_callback_info info);
    static napi_value ToESObject(napi_env env, napi_callback_info info);
    static napi_value GetValue(napi_env env, napi_callback_info info);
    static napi_value GetValues(napi_env env, napi_callback_info info);
    static yyjson_val *GetValueByKey(napi_env env, napi_callback_info info);
    static napi_value CreateNapiValueByJsonValue(napi_env env, yyjson_val *objValue);
    static napi_value CreateNapiData(napi_env env, yyjson_val *objValue, JsonDataType dataType);
    
public:
    yyjson_doc *doc_;
    yyjson_val *root_;
    char *array_buffer_data_;
    size_t array_buffer_length_;
};

#endif // HMSERIALIZATION_MASTER_JSON_NODE_H
